//-------------------------------------------------------//
// Implementation of Math::Utils functions				  //	
//------------------------------------------------------//
namespace Math
{
namespace Utils
{

//-------------------------------------------------
template <typename T>
inline T Pow2(T _val)
{ 
	return _val*_val; 
}

//--------------------------------------------------
template <typename T>
inline T PowN(T _val,int _n)
{ 
	T r=1.0f; 
	if(_n>0) 
	{
		for(int i=0;i<_n;++i)
			r*=_val; 
	}
	else if(_n<0)
	{ 
		for(int i=0; i<-_n; ++i) 
			r/=_val; 
	} 

	return r; 
}

//--------------------------------------------------
template <typename T>
inline T Log(T val)
{ 
	return (T)log(val); 
}

//--------------------------------------------------
template <typename T>
inline T LogBase(T val, T base)
{ 
	return (T)(log(val) / log(base)); 
}

//--------------------------------------------------
template <typename T>
inline T Min(T _a, T _b)
{ 
	return _a<_b ? _a : _b;  
}

//--------------------------------------------------
template <typename T>
inline T Max(T _a, T _b)
{ 
	return _a>_b ? _a : _b;  
}

//--------------------------------------------------
template <typename T>
inline T Clamp(T _val, T _min, T _max)
{ 
	T r=Min(_val,_max); 
	r=Max(r,_min);  

	return r;  
}

//--------------------------------------------------
template <typename T>
inline T Abs(T _val)
{ 
	return (T)fabs(_val); 
}

//--------------------------------------------------
template <typename T>
inline T Floor(T _val)
{ 
	return (T)floor(_val); 
}

//--------------------------------------------------
template <typename T>
inline T Ceil(T _val)
{ 
	return (T)ceil(_val); 
}

//--------------------------------------------------
template <typename T>
inline T Round(T _val)
{ 
	return Floor(_val + (T)0.5); 
}

//--------------------------------------------------
template <typename T>
inline T Exp(T _val)
{ 
	return (T)exp(_val); 
}

//--------------------------------------------------
template <typename T>
inline void	Swap(T& _a, T& _b)
{ 
	T t=_a;
	_a=_b;
	_b=t; 
}

//--------------------------------------------------
template <typename T>
inline T Lerp(const T& _a, const T& _b, const T& _lambda)
{ 
	return _a*((T)1-_lambda) + _b*_lambda; 
}

//--------------------------------------------------
template <class T>
inline bool InRangeNonSorted_Open(T const& _val, T const& _ref0, T const& _ref1)
{
	return (_val < _ref0 && _val > _ref1) || (_val < _ref1 && _val > _ref0);
}

//--------------------------------------------------
template <class T>
inline bool InRangeNonSorted_Close(T const& _val, T const& _ref0, T const& _ref1)
{
	return (_val <= _ref0 && _val >= _ref1) || (_val <= _ref1 && _val >= _ref0);
}

//--------------------------------------------------
template <class T>
inline bool IsPair(T const& _val)
{ 
	return ((_val & 0x1) == 0); 
}

//--------------------------------------------------
template <typename T>
inline bool IsPositive(T _fVal)
{
	return (*(int32*)(&fVal) & 0x80000000) == 0;
}

//------------------------------------------------
inline float Sign(float _fVal)
{
	int32 i = static_cast<int32>((*(int32*)(&_fVal) & 0x80000000 | 0x3F800000));
	return *(float*)(&i);
}

//-----------------------------------------------
inline uint32 RoundUp4(uint32 _n)
{
	if(_n & 0x3)
		return ((_n & 0xFFFFFFFC) + 0x4);
	else
		return _n;
}

//-----------------------------------------------
inline uint32 RoundUp32(uint32 _n)
{
	if(_n & 0x1F)
		return ((_n & 0xFFFFFFE0) + 0x20);
	else
		return _n;
}

//-----------------------------------------------
inline uint32 RoundDown32(uint32 _n)
{
	return (_n & 0xFFFFFFE0);
}

//-----------------------------------------------
inline bool IsPowerOf2(uint32 _n)
{
	if(_n == 0)
	{
		return false;
	}
	else
	{
		return (_n & (_n-1)) == 0;
	}
}

} //namespace Utils
} //namespace Math